package com.logica.tutorial.web;

import java.util.Arrays;
import java.util.List;

import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormValidatingBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.markup.html.form.SimpleFormComponentLabel;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.apache.wicket.util.visit.IVisit;
import org.apache.wicket.util.visit.IVisitor;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.logica.tutorial.dto.PersonDTO;
import com.logica.tutorial.model.Person;
import com.logica.tutorial.model.Sex;
import com.logica.tutorial.service.PersonService;
import com.logica.tutorial.soap.Post;
import com.logica.tutorial.soap.ZipCode;

public class SearchPage extends Panel {
	@SpringBean
	private PersonService personService;
	private Person person;
	private Sex sex = Sex.NA;
	private LoadableDetachableModel personList;
	private WebMarkupContainer personListContainer;
	private FormComponent<?> cityField;
	private FormComponent<?> streetField;
	private FormComponent<?> zipCodeField;
	
	public Sex getSex() {
		return sex;
	}
	
	public SearchPage(String id) {
		super(id);

		person = new Person();

		CompoundPropertyModel personModel = new CompoundPropertyModel(person);

		Form<Person> form = new Form<Person>("searchPageForm", personModel);
		form.setOutputMarkupId(true);
		add(form);

		final FeedbackPanel feedback = new FeedbackPanel(
				"searchPageFormFeedback");
		feedback.setOutputMarkupId(true);
		add(feedback);

		FormComponent<?> fc;
		// add form components to the form as usual

		fc = new TextField<Long>("id");
		fc.setLabel(new ResourceModel("label.Id"));
		fc.setOutputMarkupId(true);
		form.add(fc);
		form.add(new SimpleFormComponentLabel("id-label", fc));

		fc = new TextField<String>("firstName")
				.setConvertEmptyInputStringToNull(false);
		fc.setLabel(new ResourceModel("label.firstName"));
		form.add(fc);
		form.add(new SimpleFormComponentLabel("firstName-label", fc));

		fc = new TextField<String>("lastName")
				.setConvertEmptyInputStringToNull(false);
		fc.setLabel(new ResourceModel("label.lastName"));
		form.add(fc);
		form.add(new SimpleFormComponentLabel("lastName-label", fc));

		List<Sex> sexes = Arrays.asList(new Sex[] { Sex.MALE, Sex.FEMALE,
				Sex.NA });

		fc = new DropDownChoice<Object>("sex", sexes,
				new IChoiceRenderer<Object>() {
					public Object getDisplayValue(Object methodObj) {
						// Localize / Show user friendly strings
						return getString(methodObj.toString());
					}

					public String getIdValue(Object id, int index) {
						return id.toString();
					}
				});
		fc.setLabel(new ResourceModel("label.sex"));
		form.add(fc);
		form.add(new SimpleFormComponentLabel("sex-label", fc));
		
		streetField = new TextField<String>("street",
				personModel.bind("address.street"))
				.setConvertEmptyInputStringToNull(false);
		streetField.setLabel(new ResourceModel("label.street"));
//		streetField.add(new UpdateZipCodesBehavior("onchange", this,
//				zipCodePanel));
//		streetField.add(new UpdateZipCodesBehaviorDelayed("keyup", this,
//				zipCodePanel));
		form.add(streetField);
		form.add(new SimpleFormComponentLabel("street-label", streetField));

		fc = new TextField<String>("houseNr",
				personModel.bind("address.houseNr"))
				.setConvertEmptyInputStringToNull(false);
		fc.setLabel(new ResourceModel("label.houseNr"));
		form.add(fc);
		form.add(new SimpleFormComponentLabel("houseNr-label", fc));

		cityField = new TextField<String>("city",
				personModel.bind("address.city"))
				.setConvertEmptyInputStringToNull(false);
		cityField.setLabel(new ResourceModel("label.city"));
//		cityField
//				.add(new UpdateZipCodesBehavior("onchange", this, zipCodePanel));
//		cityField.add(new UpdateZipCodesBehaviorDelayed("keyup", this,
//				zipCodePanel));
		form.add(cityField);
		form.add(new SimpleFormComponentLabel("city-label", cityField));

		zipCodeField = new TextField<Integer>("zipCode",
				personModel.bind("address.zipCode"))
				.setConvertEmptyInputStringToNull(false);

		zipCodeField.setLabel(new ResourceModel("label.zipCode"));
		form.add(zipCodeField);
		form.add(new SimpleFormComponentLabel("zipCode-label", zipCodeField));
		
		form.add(new AjaxButton("searchPage-clear-button", form) {
			@Override
			protected void onSubmit(final AjaxRequestTarget target, Form form) {
				form.setModelObject(new Person());
				form.clearInput();
				target.add(form);
			}
		}.setDefaultFormProcessing(false));
		
		form.add(new AjaxButton("searchPage-submit-button", form) {

			@Override
			protected void onSubmit(final AjaxRequestTarget target, Form form) {
				person = (Person) form.getDefaultModelObject();
				
				target.add(personListContainer);
				
				form.visitChildren(TextField.class,
						new IVisitor<Component, Void>() {
							@Override
							public void component(Component component,
									final IVisit<Void> visit) {
								if (!component.hasErrorMessage()) {
									component.add(new AttributeModifier(
											"class", ""));
									target.add(component);
								}
							}
						});
				form.clearInput();
			}

			@Override
			protected void onError(final AjaxRequestTarget target, Form<?> form) {
				form.visitChildren(TextField.class,
						new IVisitor<Component, Void>() {
							@Override
							public void component(Component component,
									final IVisit<Void> visit) {
								if (component.hasErrorMessage()) {
									component.add(new AttributeModifier(
											"class", "error"));
									target.add(component);
								} else {
									component.add(new AttributeModifier(
											"class", ""));
									target.add(component);
								}
							}
						});
			}
		});

		AjaxFormValidatingBehavior.addToAllFormComponents(form, "onsubmit");
		
		personList = new LoadableDetachableModel() {
			protected Object load() {
				Post postService = new Post();
				return personService.findPerson(person);
			}
		};

		@SuppressWarnings("unchecked")
		final ListView personListView = new ListView("personList",
				personList) {
			@Override
			protected void populateItem(ListItem item) {
				final PersonDTO personItem = (PersonDTO) item.getModelObject();

				Label personItemIdLabel = new Label("personItemIdLabel",
						personItem.getId()+"");
				item.add(personItemIdLabel);
				Label personItemFirstNameLabel = new Label("personItemFirstNameLabel",
						personItem.getFirstName());
				item.add(personItemFirstNameLabel);
				Label personItemLastNameLabel = new Label("personItemLastNameLabel",
						personItem.getLastName());
				item.add(personItemLastNameLabel);
				Label personItemSexLabel = new Label("personItemSexLabel",
						personItem.getSex().toString());
				item.add(personItemSexLabel);
				Label personItemCityLabel = new Label("personItemCityLabel",
						personItem.getAddress().getCity());
				item.add(personItemCityLabel);
				Label personItemStreetLabel = new Label("personItemStreetLabel",
						personItem.getAddress().getStreet());
				item.add(personItemStreetLabel);
				Label personItemHouseNrLabel = new Label("personItemHouseNrLabel",
						personItem.getAddress().getHouseNr());
				item.add(personItemHouseNrLabel);
				
				String zipCodeOfPerson = "";
				if (personItem.getAddress().getZipCode() != null) {
					zipCodeOfPerson = personItem.getAddress().getZipCode()
							.toString();
				}
				Label personItemZipLabel = new Label("personItemZipLabel",
						zipCodeOfPerson);

				item.add(personItemZipLabel);
			}
		};
		
		personListContainer = new WebMarkupContainer(
				"personListContainer");

		personListContainer.setOutputMarkupId(true);
		personListContainer.setOutputMarkupPlaceholderTag(true);
		personListContainer.add(personListView);
		add(personListContainer);
	}
}
